package com.zhuozhou.jdyc.util.media;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;

import com.zhuozhou.jdyc.api.ConstantsHelper;
import com.zhuozhou.jdyc.main.base.activity.PermissionsActivity;
import com.zhuozhou.jdyc.util.apiUtil.FileUtils;
import com.zhuozhou.jdyc.util.apiUtil.StringUtil;
import com.zhuozhou.jdyc.util.cache.GlideCacheUtil;
import com.zhuozhou.jdyc.util.imgCompressor.ImgCompressor;
import com.zhuozhou.jdyc.util.log.LogUtil;
import com.zhuozhou.jdyc.util.videocompressor.VideoCompress;
import com.zhuozhou.jdyc.wight.dialog.OpenImageDialog;
import com.zhuozhou.jdyc.wight.dialog.OpenShootDialog;
import com.zhuozhou.jdyc.wight.multi_image_selector.MultiImageSelector;

import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

/**
 * Created by fz on 2021/2/5 14:19
 * describe:拍照、拍摄视频、图片视频压缩工具类
 */
public class MediaHelper implements OpenImageDialog.OnOpenImageClickListener,
        ImgCompressor.CompressListener, OpenShootDialog.OnOpenVideoClickListener {
    private final MutableLiveData<MediaBean> mutableLiveData = new MutableLiveData<>();
    private final MutableLiveData<MediaBean> mutableLiveDataCompress = new MutableLiveData<>();
    private Uri imageUri;
    static String[] PERMISSIONS_CAMERA = new String[]{
            Manifest.permission.CAMERA,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    static String[] PERMISSIONS_READ = new String[]{
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    private List<String> imageList = new ArrayList<>();
    private List<String> videoList = new ArrayList<>();
    private List<String> imagesCompressList;
    private List<String> videoCompressList;

    /**
     * 低质量
     */
    public final static int VIDEO_HIGH = 1;
    /**
     * 中等质量
     */
    public final static int VIDEO_MEDIUM = 2;
    /**
     * 高质量
     */
    public final static int VIDEO_LOW = 3;

    /**
     * 最大可选的图片数量，默认9张
     */
    public final static int ALBUM_MAX_COUNT = 9;

    /**
     * 当前已选择的图片数量
     */
    private int mCurrentImageCount;

    private MediaBuilder mediaBuilder;

    protected MediaHelper(MediaBuilder mediaBuilder) {
        this.mediaBuilder = mediaBuilder;
    }

    public MutableLiveData<MediaBean> getMutableLiveData() {
        return mutableLiveData;
    }

    public MutableLiveData<MediaBean> getMutableLiveDataCompress() {
        return mutableLiveDataCompress;
    }

    /**
     * 当前已经选择的图片数量，记得必须实时更新
     *
     * @param mCurrentImageCount 已选择图片数量
     */
    public void setCurrentImageCount(int mCurrentImageCount) {
        this.mCurrentImageCount = mCurrentImageCount;
    }

    public void openImageDialog(View v) {
        new OpenImageDialog(v.getContext())
                .setOnOpenImageClickListener(this)
                .builder()
                .show();
    }

    public Uri getImageUri() {
        return imageUri;
    }

    /**
     * 权限检测
     *
     * @param permissions 权限
     * @param requestCode 请求码
     */
    private void checkPermission(String[] permissions, int requestCode) {
        if (mediaBuilder.getFragment() != null) {
            PermissionsActivity.startActivityForResult(mediaBuilder.getFragment().getActivity(), requestCode, permissions);
        } else if (mediaBuilder.getActivity() != null) {
            PermissionsActivity.startActivityForResult(mediaBuilder.getActivity(), requestCode, permissions);
        }
    }

    /**
     * 开始压缩
     */
    public void startCompressImage(List<String> images) {
        this.imagesCompressList = images == null ? new ArrayList<>() : images;
        imageList.clear();
        mediaBuilder.getBaseView().showLoading("正在处理图片...");
        Message message = new Message();
        message.what = 0;
        handlerImage.sendMessage(message);
    }

    /**
     * 处理图片压缩
     */
    private final Handler handlerImage = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            try {
                if (imagesCompressList == null || imagesCompressList.size() == 0 ||
                        msg.what >= imagesCompressList.size()) {
                    mediaBuilder.getBaseView().hideLoading();
                    mutableLiveDataCompress.postValue(new MediaBean(imageList, MediaTypeEnum.IMAGE.getMediaType()));
                } else {
                    LogUtil.show(imagesCompressList.get(msg.what) + "压缩前大小：" + GlideCacheUtil.getFormatSize(FileUtils.getFileSize(imagesCompressList.get(msg.what))));
                    if (FileUtils.getFileSize(imagesCompressList.get(msg.what)) < 200 * 1024 || mediaBuilder.getImageQualityCompress() == 0) {
                        LogUtil.show("该图片小于200kb不压缩或者已手动设置为不压缩");
                        imageList.add(imagesCompressList.get(msg.what));
                        Message message = new Message();
                        message.what = imageList.size();
                        handlerImage.sendMessage(message);
                    } else {
                        ImgCompressor.getInstance(mediaBuilder.getContext())
                                .withListener(MediaHelper.this).
                                starCompress(imagesCompressList.get(msg.what), 600, 800, mediaBuilder.getImageQualityCompress());
                    }
                }
            } catch (Exception e) {
                LogUtil.e(e);
                e.printStackTrace();
                mediaBuilder.getBaseView().showToast("图片加载出现错误");
                mediaBuilder.getBaseView().hideLoading();
            }
            return false;
        }
    });

    @Override
    public void onCompressStart() {

    }

    @Override
    public void onCompressEnd(ImgCompressor.CompressResult imageOutPath) {
        if (imageOutPath.getStatus() == ImgCompressor.CompressResult.RESULT_ERROR) {
            mediaBuilder.getBaseView().hideLoading();
            mediaBuilder.getBaseView().showToast("图片压缩错误");
            return;
        }
        try {
            LogUtil.show("压缩后图片大小：" + GlideCacheUtil.getFormatSize(FileUtils.getFileSize(imageOutPath.getOutPath())));
            imageList.add(imageOutPath.getOutPath());
            Message message = new Message();
            message.what = imageList.size();
            handlerImage.sendMessage(message);
        } catch (Exception e) {
            mediaBuilder.getBaseView().showToast("图片压缩错误");
            mediaBuilder.getBaseView().hideLoading();
            e.printStackTrace();
        }
    }

    /**
     * 打开相册选择页面
     */
    public void openImg(int lastCount) {
        MultiImageSelector selector = MultiImageSelector.create();
        selector.showCamera(false);
        if (mediaBuilder.getImageAlbumCount() == 1) {
            selector.single();
        } else {
            selector.count(mediaBuilder.getImageAlbumCount() > lastCount ? mediaBuilder.getImageAlbumCount() - lastCount : 0);
            selector.multi();
        }
        if (mediaBuilder.getFragment() != null) {
            selector.start(mediaBuilder.getFragment(), ConstantsHelper.CHOOSE_PICTURE);
        } else if (mediaBuilder.getActivity() != null) {
            selector.start(mediaBuilder.getActivity(), ConstantsHelper.CHOOSE_PICTURE);
        }
    }

    /**
     * 打开摄像机
     */
    public void camera() {
        // 激活相机
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // 判断存储卡是否可以用，可用进行存储
        String filename = Calendar.getInstance().getTimeInMillis() + "";
        File tempFile = new File(mediaBuilder.getImageOutPutPath(), filename + ".jpg");
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            // 从文件中创建uri
            imageUri = Uri.fromFile(tempFile);
        } else {
            //兼容android7.0 使用共享文件的形式
            ContentValues contentValues = new ContentValues(1);
            contentValues.put(MediaStore.Images.Media.DATA, tempFile.getAbsolutePath());
            imageUri = mediaBuilder.getContext().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
        }
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        if (mediaBuilder.getFragment() != null) {
            mediaBuilder.getFragment().startActivityForResult(intent, ConstantsHelper.PHOTO_REQUEST_CAMERA);
        } else if (mediaBuilder.getActivity() != null) {
            mediaBuilder.getActivity().startActivityForResult(intent, ConstantsHelper.PHOTO_REQUEST_CAMERA);
        }
    }

    /**
     * uri转本地的绝对路径
     *
     * @return 本地文件绝对路径
     */
    public String getFilePathFromContentUri() {
        String filePath = null;
        String[] filePathColumn = {MediaStore.MediaColumns.DATA};
        if (imageUri == null) {
            return null;
        }
        Cursor cursor = mediaBuilder.getContext().getContentResolver().query(imageUri, filePathColumn, null, null, null);
        if (cursor != null) {
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            filePath = cursor.getString(columnIndex);
            cursor.close();
        }
        return filePath;
    }

    /**
     * 开始压缩
     */
    public void startCompressVideo(List<String> videos) {
        this.videoCompressList = videos == null ? new ArrayList<>() : videos;
        videoList.clear();
        mediaBuilder.getBaseView().showLoading("正在处理视频...");
        Message message = new Message();
        message.what = 0;
        handlerVideo.sendMessage(message);
    }

    /**
     * 处理视频压缩
     */
    private Handler handlerVideo = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            try {
                if (videoCompressList == null || videoCompressList.size() == 0 ||
                        msg.what >= videoCompressList.size()) {
                    mediaBuilder.getBaseView().hideLoading();
                    mutableLiveDataCompress.postValue(new MediaBean(videoList, MediaTypeEnum.VIDEO.getMediaType()));
                } else {
                    String pathName = StringUtil.replace(UUID.randomUUID().toString(), "-", "") +
                            "." + FileUtils.getFileExtension(videoCompressList.get(msg.what));
                    if (mediaBuilder.getVideoQuality() == VIDEO_HIGH) {
                        VideoCompress.compressVideoHigh(videoCompressList.get(msg.what),
                                mediaBuilder.getVideoOutPutPath() + File.separator + pathName,
                                new VideoCompressListener(mediaBuilder.getVideoOutPutPath() + File.separator + pathName));
                    } else if (mediaBuilder.getVideoQuality() == VIDEO_MEDIUM) {
                        VideoCompress.compressVideoMedium(videoCompressList.get(msg.what),
                                mediaBuilder.getVideoOutPutPath() + File.separator + pathName,
                                new VideoCompressListener(mediaBuilder.getVideoOutPutPath() + File.separator + pathName));
                    } else {
                        VideoCompress.compressVideoLow(videoCompressList.get(msg.what),
                                mediaBuilder.getVideoOutPutPath() + File.separator + pathName,
                                new VideoCompressListener(mediaBuilder.getVideoOutPutPath() + File.separator + pathName));
                    }
                }
            } catch (Exception e) {
                LogUtil.e(e);
                e.printStackTrace();
                mediaBuilder.getBaseView().showToast("视频加载出现错误");
                mediaBuilder.getBaseView().hideLoading();
            }
            return false;
        }
    });

    /**
     * 视频压缩监听回调方法
     */
    public class VideoCompressListener implements VideoCompress.CompressListener {
        private String outPath;

        public VideoCompressListener(String outPath) {
            this.outPath = outPath;
        }

        @Override
        public void onStart() {

        }

        @Override
        public void onSuccess() {
            videoList.add(outPath);
            Message message = new Message();
            message.what = videoList.size();
            handlerVideo.sendMessage(message);
        }

        @Override
        public void onFail() {
            mediaBuilder.getBaseView().showToast("视频压缩异常");
            mediaBuilder.getBaseView().hideLoading();
        }

        @Override
        public void onProgress(float percent) {

        }
    }


    @Override
    public void shootClick(int mediaType) {
        if (OpenShootDialog.ALBUM == mediaType) {
            if (mediaBuilder.getPermissionsChecker().lacksPermissions(PERMISSIONS_READ)) {
                checkPermission(PERMISSIONS_READ, ConstantsHelper.SHOOT_ALBUM_REQUEST_CODE);
                return;
            }
            openShoot();
        } else if (OpenShootDialog.CAMERA == mediaType) {
            if (mediaBuilder.getPermissionsChecker().lacksPermissions(PERMISSIONS_CAMERA)) {
                checkPermission(PERMISSIONS_CAMERA, ConstantsHelper.SHOOT_REQUEST_CODE);
                return;
            }
            shoot();
        }
    }

    /**
     * 打开拍摄
     */
    public void shoot() {
        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
        intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, mediaBuilder.getMaxVideoTime());
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            String filename = Calendar.getInstance().getTimeInMillis() + "";
            File tempFile = new File(mediaBuilder.getVideoOutPutPath() + File.separator + filename + ".mp4");
            Uri imageUri;
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                // 从文件中创建uri
                imageUri = Uri.fromFile(tempFile);
            } else { //兼容android7.0 使用共享文件的形式
                ContentValues contentValues = new ContentValues(1);
                contentValues.put(MediaStore.Video.Media.DATA, tempFile.getAbsolutePath());
                imageUri = mediaBuilder.getContext().getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        }
        if (mediaBuilder.getFragment() != null) {
            mediaBuilder.getFragment().startActivityForResult(intent, ConstantsHelper.CAMERA_SHOOT_REQUEST_CODE);
        } else if (mediaBuilder.getActivity() != null) {
            mediaBuilder.getActivity().startActivityForResult(intent, ConstantsHelper.CAMERA_SHOOT_REQUEST_CODE);
        }
    }

    /**
     * 打开视频资源选择库
     */
    @SuppressLint("IntentReset")
    private void openShoot() {
        Intent videoIntent = new Intent(Intent.ACTION_PICK);
        videoIntent.setData(MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
        videoIntent.setType("video/*");
        if (mediaBuilder.getFragment() != null) {
            mediaBuilder.getFragment().startActivityForResult(videoIntent, ConstantsHelper.OPEN_SHOOT_ALBUM_REQUEST_CODE);
        } else if (mediaBuilder.getActivity() != null) {
            mediaBuilder.getActivity().startActivityForResult(videoIntent, ConstantsHelper.OPEN_SHOOT_ALBUM_REQUEST_CODE);
        }
    }

    /**
     * 获取视频地址
     *
     * @param data 回调intent
     * @return 视频路径
     */
    public void videoAlbumResult(Intent data) {
        if (data == null || data.getData() == null) {
            return;
        }
        Cursor cursor = mediaBuilder.getContext().getContentResolver().query(data.getData(), null, null, null, null);
        if (cursor == null) {
            return;
        }
        if (cursor.moveToFirst()) {
            String videoPath = cursor.getString(cursor.getColumnIndex(MediaStore.Video.VideoColumns.DATA));
            LogUtil.show("视频：" + videoPath);
            mutableLiveData.postValue(new MediaBean(new ArrayList<>(Collections.emptyList()), MediaTypeEnum.IMAGE.getMediaType()));
        }
        cursor.close();
    }

    /**
     * 拍摄视频后的回调
     *
     * @param data
     */
    public void shootResult(Intent data) {
        Uri uri = data.getData();
        if (uri == null) {
            return;
        }
        Cursor cursor = mediaBuilder.getContext().getContentResolver().query(uri, null, null, null, null);
        if (cursor != null && cursor.moveToNext()) {
            // 视频路径
            String filePath = cursor.getString(cursor.getColumnIndex(MediaStore.Video.VideoColumns.DATA));
            LogUtil.show("filePath:" + filePath);
            if (FileUtils.getFileSize(filePath) > 50 * 1024 * 1024) {
                mediaBuilder.getBaseView().showToast("最多只能选择50M以内");
                return;
            }
            mutableLiveData.postValue(new MediaBean(new ArrayList<>(Collections.singletonList(filePath)), MediaTypeEnum.VIDEO.getMediaType()));
        }
        if (cursor != null) {
            cursor.close();
        }
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case ConstantsHelper.PHOTO_REQUEST_CAMERA:
                if (resultCode == Activity.RESULT_OK) {
                    String cameraPath = getFilePathFromContentUri();
                    if (StringUtil.isEmpty(cameraPath)) {
                        mediaBuilder.getBaseView().showToast("图片加载错误");
                        return;
                    }
                    mutableLiveData.postValue(new MediaBean(new ArrayList<>(Collections.singletonList(cameraPath)), MediaTypeEnum.IMAGE.getMediaType()));
                }
                break;
            case ConstantsHelper.CHOOSE_PICTURE:
                if (resultCode == Activity.RESULT_OK) {
                    List<String> mSelectPath = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT);
                    mutableLiveData.postValue(new MediaBean(mSelectPath, MediaTypeEnum.IMAGE.getMediaType()));
                }
                break;
            case ConstantsHelper.CAMERA_SHOOT_REQUEST_CODE:
                if (resultCode == Activity.RESULT_OK && data != null) {
                    shootResult(data);
                }
                break;
            case ConstantsHelper.OPEN_SHOOT_ALBUM_REQUEST_CODE:
                if (resultCode == Activity.RESULT_OK) {
                    videoAlbumResult(data);
                }
                break;
            case ConstantsHelper.CAMERA_REQUEST_CODE:
                if (resultCode == PermissionsActivity.PERMISSIONS_GRANTED) {
                    camera();//获取权限后打开相机
                } else {
                    mediaBuilder.getBaseView().showToast("权限被拒绝，相机打开失败");
                }
                break;
            case ConstantsHelper.PHOTO_REQUEST_CODE:
                if (resultCode == PermissionsActivity.PERMISSIONS_GRANTED) {
                    openImg(mCurrentImageCount);
                } else {
                    mediaBuilder.getBaseView().showToast("权限被拒绝，相册打开失败");
                }
                break;
            case ConstantsHelper.SHOOT_REQUEST_CODE:
                if (resultCode == PermissionsActivity.PERMISSIONS_GRANTED) {
                    shoot();//获取权限后打开摄像
                } else {
                    mediaBuilder.getBaseView().showToast("权限被拒绝，相机打开失败");
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void mediaClick(int mediaType) {
        if (OpenImageDialog.ALBUM == mediaType) {
            if (mediaBuilder.getPermissionsChecker().lacksPermissions(PERMISSIONS_READ)) {
                checkPermission(PERMISSIONS_READ, ConstantsHelper.PHOTO_REQUEST_CODE);
                return;
            }
            openImg(mCurrentImageCount);
        } else if (OpenImageDialog.CAMERA == mediaType) {
            if (mediaBuilder.getPermissionsChecker().lacksPermissions(PERMISSIONS_CAMERA)) {
                checkPermission(PERMISSIONS_CAMERA, ConstantsHelper.CAMERA_REQUEST_CODE);
                return;
            }
            camera();
        }
    }

}
